#include <iostream>
#include <unistd.h>
#include <mutex>
#include <thread>
#include <atomic>
#include <condition_variable>
using namespace std;

// void my_thread()
// {
//     std::cout << "Thread started" << std::endl;
//     std::this_thread::sleep_for(std::chrono::seconds(5));
//     std::cout << "Thread ended" << std::endl;
// }

// int main()
// {
//     std::thread t(my_thread);

//     if (t.joinable())
//     {
//         std::cout << "Thread is joinable" << std::endl;
//         t.join();
//     }
//     else
//     {
//         std::cout << "Thread is not joinable" << std::endl;
//     }

//     return 0;
// }

// void *threadFunction(void *arg)
// {
// 	// 线程函数的逻辑
// 	sleep(5);
// 	return nullptr;
// }

// int main()
// {
// 	pthread_t thread;
// 	// 创建线程并执行线程函数
// 	pthread_create(&thread, nullptr, threadFunction, nullptr);
// 	int res;
// 	// 尝试非阻塞等待线程函数
// 	while (res = pthread_tryjoin_np(thread, nullptr))
// 	{
// 		if (res == EBUSY)
// 		{
// 			std::cout << "线程尚未结束" << std::endl;
// 		}
// 		else
// 		{
// 			std::cout << "出现错误" << std::endl;
// 		}
// 		sleep(1);
// 	}

// 	std::cout << "线程成功结束" << std::endl;

// 	return 0;
// }

// mutex
// int main()
// {
//     mutex mtx;
//     int x = 0;
//     int n = 100000;

//     auto threadfunc = [&, n]()
//     {
//         mtx.lock();
//         for (int i = 0; i < n; ++i)
//         {
//             ++x;
//         }
//         mtx.unlock();
//     };
//     thread t1(threadfunc);
//     thread t2(threadfunc);

//     t1.join();
//     t2.join();
//     cout << x << endl;
//     return 0;
// }

// recursize_mutex
// int x = 0;

// void threadfunc(int n, recursive_mutex *mtx)
// {
//     if(n == 0)
//         return;
//     mtx->lock();
//     ++x;
//     threadfunc(n-1, mtx);
//     mtx->unlock();
// }

// int main()
// {
//     recursive_mutex mtx;

//     thread t1(threadfunc, 100000, &mtx);
//     thread t2(threadfunc, 200000, &mtx);

//     t1.join();
//     t2.join();
//     cout << x << endl;
//     return 0;
// }

// lock_guard && unique_lock
// int x = 0;
// mutex mtx;

// void threadfunc(int n)
// {

//     for (int i = 0; i < n; ++i)
//     {
//         try
//         {
//             // mtx.lock();
//             // lock_guard和unique_lock会在构造时加锁，析构时解锁
//             lock_guard<mutex> lock(mtx);
//             // unique_lock<mutex> lock(mtx);
//             ++x;
//             // 抛异常，会跳过unlock函数使程序不能继续执行
//             if (rand() % 3 == 0)
//             {
//                 throw exception();
//             }
//             // mtx.unlock();
//         }
//         catch (const exception &e)
//         {
//             cerr << "抛异常" << endl;
//         }
//     };
// }

// int main()
// {
//     srand((unsigned int)time(nullptr));
//     thread t1(threadfunc, 10);
//     thread t2(threadfunc, 20);

//     t1.join();
//     t2.join();
//     cout << x << endl;
//     return 0;
// }

// atomic
// int main()
// {
//     atomic<int> x(0);
//     int n = 1000000;

//     auto threadfunc = [&, n]()
//     {
//         for (int i = 0; i < n; ++i)
//         {
//             x+=2;
//         }
//     };
//     thread t1(threadfunc);
//     thread t2(threadfunc);

//     t1.join();
//     t2.join();
//     printf("%d\n",x.load());
//     return 0;
// }

// 1~100，t1打印奇数，t2打印偶数
// int main()
// {
//     mutex mtx;
//     int x = 1;
//     int n = 12345;
//     condition_variable cv;

//     thread t1([&, n]()
//               {
//                   while (x<=n)
//                   {
//                       unique_lock<mutex> lock(mtx);

//                     // if(x > n) break;
//                     // wait参数：unique_lock, 通关条件
//                     cv.wait(lock, [&](){return x%2 == 1;});
//                     // 等效的实现方法：
//                     //   while (!(x % 2 == 1)) // 防止伪唤醒
//                     //   {
//                     //       cv.wait(lock);
//                     //   }
//                     if(x > n) break;
//                     cout << "[t1]" << ":" << x << endl;
//                     ++x;
//                     cv.notify_one();
//                   } });

//     thread t2([&, n]()
//               {
//                 while(x<=n)
//                 {
//                     unique_lock<mutex> lock(mtx);

//                     // if(x > n) break;
//                     cv.wait(lock, [&](){return x%2==0;});
//                     // 等效的实现方法：
//                     // while(!(x%2 == 0))
//                     // {
//                     //     cv.wait(lock);
//                     // }
//                     if(x > n) break;
//                     cout << "[t2]" << ":" << x << endl;
//                     ++x;
//                     cv.notify_one();
//                 } });

//     t1.join();
//     t2.join();
//     return 0;
// }

// 线程函数的参数
#include <thread>

int k = 0;

void ThreadFunc1(int *x)
{
    *x += 10;
}

void ThreadFunc2(int &x)
{
    x += 10;
}

class A
{
public:
    int i = 10;
    static void ThreadFunc3()
    {
        k += 10;
    }
    void ThreadFunc4()
    {
        i += 101;
    }
};

int main()
{

    // 线程函数的参数可以传外部变量的地址（将地址拷贝到线程独立栈）
    thread t1(ThreadFunc1, &k);
    t1.join();
    cout << k << endl;

    // 线程函数的参数不能直接传外部变量的引用（实际引用的是线程栈中的拷贝）
    // thread t2(ThreadFunc2, k); // 在线程函数中对k修改，不会影响外部实参，有些编译器可能直接编译报错
    thread t2(ThreadFunc2, std::ref(k)); // 如果想要通过形参改变外部实参，必须借助std::ref()函数传引用
    t2.join();
    cout << k << endl;

    // 静态成员函数和普通函数类似，只是需要注明类域
    thread t3(A::ThreadFunc3); // 取静态成员函数的地址可以不加&
    t3.join();
    cout << k << endl;

    // 非静态成员函数作线程函数时，必须将this指针（调用对象的地址）作为线程函数的参数。
    A a;
    thread t4(&A::ThreadFunc4, &a); // 取非静态成员函数的地址必须加&
    t4.join();
    cout << a.i << endl;
    return 0;
}
